# 先卸载 Crypto 和 pycryptodome 然后重新安装 pycryptodome # 解决windows no mudule name... 报错问题
# pip install pycryptodome
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import hashlib
import json
import re
import time
import datetime
import hmac
import random
import base64
import jwt


def php_encryption_phone(phone_num):
    """
    手机号通过php代码加密，返回加密后手机号
    """
    print("php加密前手机号:", phone_num)
    data = str(phone_num)
    key = "w4lUgqr7cOybf5nrhPQBk7kJZtydD8Kk"
    # 对key 做两次sha1加密
    # digest 二进制
    key = hashlib.sha1(key.encode()).digest()
    key = hashlib.sha1(key).digest()
    # 截取16位
    key = key[0:16]
    BLOCK_SIZE = 16
    # AES 堆成加密
    cipher = AES.new(key, AES.MODE_ECB)
    msg = cipher.encrypt(pad(data.encode(), BLOCK_SIZE))
    msg = base64.b64encode(msg).decode()
    print("php加密后手机号:", msg)
    return msg


def base64url(source):
    """
    传入字节类型，base64编码，替换指定字符，返回编码后的字符串
    :param source:  字节byte类型
    """
    # base64.b64encode 生成的结果不包含尾部\n换行符   # ***  base64.encodebytes() 结果尾部会出现 \n 换行
    encoded_source = base64.b64encode(source).decode()

    # 不进行如下替换与jwt库直接生成的token有差异
    # 替换末尾 = 为 ''
    encoded_source = re.sub(pattern=r'=+$', repl='', string=encoded_source)
    # 替换 + 为 -
    encoded_source = re.sub(pattern=r'\+', repl='-', string=encoded_source)
    # 替换 / 为 _
    encoded_source = re.sub(pattern=r'\/', repl='_', string=encoded_source)
    return encoded_source


def get_jwt(header, payload):
    """
    生成 jwt 加密串
    """

    header = json.dumps(header, separators=(',', ':'))
    payload = json.dumps(payload, separators=(",", ":"))

    encode_header = base64url(header.encode())
    encode_payload = base64url(payload.encode())

    token = encode_header + "." + encode_payload

    secret = 'sgu8msctlxpcu1b9d1ccys6adqky877a'

    sign = hmac.new(key=secret.encode(), msg=token.encode(), digestmod=hashlib.sha256).digest()
    sign = base64url(sign)
    jwt = token + "." + sign

    return jwt


def get_work_order_id():
    """
    生成work_order_id
    14位字母和数字组合
    """
    # 造数工具数据前四位XPCS
    work_order_id = "XPCS"
    # 所有大写字母
    letter = [chr(i) for i in range(65, 91)]
    # 数字0-9
    number = list(range(10))
    letter.extend(number)
    work_order_id += ''.join([str(random.choice(letter)) for i in range(10)])
    return work_order_id


def convert_timestamp(date_time_str):
    """
    传入日期时间，转换为时间戳返回
    date_time_str ex: "2022-08-12 10:00:00" 、 "2022-8-1 00:00:00" 、 "2021-12-31"
    """
    stamp = None
    try:
        # datetime.datetime.strptime 转换字符串为datatime时间类型  .timetuple 返回时间元组
        stamp = datetime.datetime.strptime(date_time_str, "%Y-%m-%d %H:%M:%S").timetuple()
    except ValueError:
        pass

    try:
        stamp = datetime.datetime.strptime(date_time_str, "%Y-%m-%d").timetuple()
    except ValueError:
        pass

    if stamp:
        # time.mktime 返回时间戳，单位秒，类型float
        return int(time.mktime(stamp)) * 1000
    else:
        print("转换时间戳异常，请按格式输入！！！ ex: 2022-08-12 10:00:00")
        return


header = {
    'typ': 'JWT',
    'alg': 'HS256'
}

# 输出时间戳秒 # 1717670063
iat = int(time.mktime(datetime.datetime.now().timetuple()))

payload = {
    'iat': iat,
    'iss': '7xkeqzwfzemtev6ko13ymi9pf0pv5q0u',
    'exp': iat + 180
}


jwt1 = get_jwt(header, payload)
print(jwt1, type(jwt1))

jwt_salt = 'sgu8msctlxpcu1b9d1ccys6adqky877a'

jwt2 = jwt.encode(payload=payload, key=jwt_salt, algorithm="HS256", headers=header)
print(jwt2, type(jwt2))

# 验证原有编写的手动jwt代码 与 PyJwt库生成的 token # 比对结果一致
for i in range(1000):
    jwt1 = get_jwt(header, payload)
    jwt2 = jwt.encode(headers=header, payload=payload, key=jwt_salt, algorithm="HS256")
    assert jwt1 == jwt2

